home *** CD-ROM | disk | FTP | other *** search
- /*
- * cellog.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* CELLOG: program performs cellular logic based on crossing number and
- * factor number
- * usage: cellog inimg outimg [-f FAC_THRESH] [-c CONNECTIVITY]
- * [-i ITERATIONS] [-o OPERATION] [-I] [-L]
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "tiffimage.h" /* picfile info on images */
- #include "images.h"
- extern void print_sos_lic ();
-
- #define ON 255 /* binarization values */
- #define OFF 0
- #define FAC_THRESH_DFLT 5 /* default threshold on factor number */
- #define NITER_DFLT 1 /* default threshold on number iteratoins */
-
- long crossnum (long *, long);
- int usage (short);
- int input (int, char **, long *, short *, long *, long *, long *);
-
- main (argc, argv)
- int argc;
- char *argv[];
-
- {
- Image *imgI, *imgO; /* input and output image structures */
- unsigned char **imgIn, **imgOut; /* input and output image arrays */
- long width, height; /* size of image */
- long facThresh; /* factor number threshold */
- short connectFlag; /* =1 to retain connectivity; 0 otherwise */
- long nIter; /* number of iterations to perform */
- long opType; /* operation type */
- long invertFlag; /* invert input image before processing */
- long xEnd, yEnd; /* end of image within 1-pixel borders */
- long ring[8]; /* neighborhood ring, top=ring[0] */
- long fNum, cNum; /* factor number and crossing number */
- long nChange; /* number pixels changed on iteration */
- long x, y, i, n;
-
- /* user input */
- if ((input (argc, argv, &facThresh, &connectFlag, &nIter, &opType, &invertFlag)) < 0)
- return (-1);
-
- /* factor number has greater effect for larger number; number entered by
- * user is for dilation, so for erosion, invert threshold value */
- if (opType == 2 || opType == 4)
- facThresh = 7 - facThresh;
-
- /* open input and output image */
- imgI = ImageIn (argv[1]);
- imgIn = ImageGetPtr (imgI);
- height = ImageGetHeight (imgI);
- width = ImageGetWidth (imgI);
- printf ("Input mage size is %dx%d.\n", width, height);
-
- /* invert image */
- if (invertFlag) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgIn[y][x] = 255 - imgIn[y][x];
- }
- imgO = ImageAlloc (height, width, 8);
- imgOut = ImageGetPtr (imgO);
-
- /* zero image borders */
- yEnd = height - 1;
- xEnd = width - 1;
- for (y = 0; y < height; y++)
- imgIn[y][0] = imgIn[y][xEnd] = OFF;
- for (x = 0; x < width; x++)
- imgIn[0][x] = imgIn[yEnd][x] = OFF;
-
- /* write input to output image */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgOut[y][x] = imgIn[y][x];
-
- /* perform cellular logic iterations */
- for (n = 0; n < nIter; n++) {
- nChange = 0;
- for (y = 1; y < yEnd; y++) {
- for (x = 1; x < xEnd; x++) {
- ring[0] = (imgIn[y - 1][x] > 0) ? 1 : 0;
- ring[1] = (imgIn[y - 1][x + 1] > 0) ? 1 : 0;
- ring[2] = (imgIn[y][x + 1] > 0) ? 1 : 0;
- ring[3] = (imgIn[y + 1][x + 1] > 0) ? 1 : 0;
- ring[4] = (imgIn[y + 1][x] > 0) ? 1 : 0;
- ring[5] = (imgIn[y + 1][x - 1] > 0) ? 1 : 0;
- ring[6] = (imgIn[y][x - 1] > 0) ? 1 : 0;
- ring[7] = (imgIn[y - 1][x - 1] > 0) ? 1 : 0;
- for (i = 0, fNum = 0; i < 8; i++)
- fNum += ring[i];
- cNum = crossnum (ring, 8);
- if (connectFlag == 1 && cNum > 1);
- else {
- switch (opType) {
- case 1: /* dilation */
- if (fNum > facThresh) {
- imgOut[y][x] = ON;
- nChange++;
- }
- break;
- case 2: /* erosion */
- if (fNum < facThresh) {
- imgOut[y][x] = OFF;
- nChange++;
- }
- break;
- case 3: /* dilation-erosion */
- if (fNum > facThresh) {
- imgOut[y][x] = ON;
- nChange++;
- }
- break;
- case 4: /* erosion-dilation */
- if (fNum < facThresh) {
- imgOut[y][x] = OFF;
- nChange++;
- }
- break;
- default:
- usage (1);
- }
- }
- }
- }
- printf ("iteration %d: nChange = %d\n", n, nChange);
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgIn[y][x] = imgOut[y][x];
- if (opType == 4) {
- opType = 3;
- facThresh = 7 - facThresh;
- }
- else if (opType == 3) {
- opType = 4;
- facThresh = 7 - facThresh;
- }
- }
-
- /* un-invert image */
- if (invertFlag) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- imgOut[y][x] = 255 - imgOut[y][x];
- }
-
- ImageOut (argv[2], imgO);
-
- return (0);
- }
-
- /* CROSSNUM: function calculates crossing number
- * usage: crossnum (ring, nRing)
- */
-
- long
- crossnum (ring, nRing)
- long *ring; /* ring of neighbors around center pixel */
- long nRing; /* number of neighbors in ring */
-
- {
- long cNum; /* crossing number result */
- long lower, upper; /* lower and upper members of ring */
- long i, m, n, k;
-
- k = 3;
-
- /* calculate CNUM, first skipping corners */
- for (i = 2, cNum = 0; i < nRing; i++) {
- lower = (long) ring[i - 1];
- if ((i % (k - 1)) == 0)
- i++; /* skip the corner pixels */
- upper = (long) ring[i];
- if (upper != 0 && lower == 0)
- cNum++;
- }
- if (ring[1] != 0 && ring[nRing - 1] == 0)
- cNum++;
-
- /* CNUM at corners */
- for (n = 1; n < 4; n++) {
- m = n * (k - 1);
- if (ring[m] != 0) {
- if (ring[m - 1] == 0 && ring[m + 1] == 0)
- cNum++;
- }
- }
- if (ring[0] != 0)
- if (ring[1] == 0 && ring[nRing - 1] == 0)
- cNum++;
-
- return (cNum);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- int
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: cellog inimg outimg [-f FAC_THRESH] [-c CONNECTIVITY]\n");
- printf (" [-i ITERATIONS] [-o OPERATION] [-I] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\ncellog performs cellular logic of input binary image.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: input image filename (TIF)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -f FAC_THRESH: factor number threshold, above which operation\n");
- printf (" performed; (default = %d, range= 0-7)\n", FAC_THRESH_DFLT);
- printf (" smaller the threshold value, the larger the effect\n");
- printf (" -c: flag to maintain connectivity; default is not set.\n");
- printf (" NOTE: this does not guarantee retention of,\n");
- printf (" only maintains it better than not;\n");
- printf (" if absolute retention is required,\n");
- printf (" use KFILL or THIN program, depending on purpose.\n");
- printf (" -i ITERATIONS: number of iterations to perform;\n");
- printf (" (default = %d)\n", NITER_DFLT);
- printf (" -o OPERATION: for dilation(1), erosion(2), closing(3),\n");
- printf (" or opening(4) (default = 1).\n");
- printf (" closing operation is alternating dilation-erosion;\n");
- printf (" opening operation is alternating erosion-dilation;\n");
- printf (" for opening or closing, the number of iterations is\n");
- printf (" the sum of the comprising dilation and erosion iterations.\n");
- printf (" -I: invert input image before processing\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &facThresh, &connectFlag
- * &nIter, &opType);
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- int
- input (argc, argv, facThresh, connectFlag, nIter, opType, invertFlag)
- int argc;
- char *argv[];
- long *facThresh; /* factor number threshold */
- short *connectFlag; /* =1 to retain connectivity; 0 otherwise */
- long *nIter; /* number of iterations to perform */
- long *opType; /* operation type */
- long *invertFlag; /* invert input image before processing */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *facThresh = FAC_THRESH_DFLT;
- *connectFlag = 0;
- *nIter = NITER_DFLT;
- *opType = 1;
- *invertFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-f") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *facThresh = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-c") == 0)
- *connectFlag = 1;
- else if (strcmp (argv[n], "-i") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *nIter = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-o") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *opType = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-I") == 0)
- *invertFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- return (0);
- }
-